package org.wlgzs.office_exam_student.view.freemarker;

import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wlgzs.office_exam_student.view.View;
import org.wlgzs.office_exam_student.view.ViewFactory;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateExceptionHandler;
import freemarker.template.TemplateModelException;

public class FMViewFactory implements ViewFactory{
	
	private final Logger logger = LoggerFactory.getLogger(this.getClass());
	
	private final static String SUFFIX = ".ftl";
	private final static String CONFIG_FILE="view.properties";
	private final static String CONFIG_VARS_PREFIX = "var.";
	private final Configuration cfg = new Configuration(Configuration.VERSION_2_3_22);
	private final Map<String,Object> globalData = new ConcurrentHashMap<>();
	
	public FMViewFactory(String templateDir) {
        try {
			cfg.setDirectoryForTemplateLoading(new File(templateDir));
		} catch (IOException e) {
			e.printStackTrace();
		}
		cfg.setDefaultEncoding("UTF-8");
		cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
		cfg.setNumberFormat("#");
		cfg.unsetCacheStorage();
	}
	
	@Override
	public View getView(String name) {
		if(!name.endsWith(SUFFIX)) {
			name += SUFFIX;
		}
		try {
			Template tem = cfg.getTemplate(name);
			return new FMView(tem);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
	@Override
	public void addGlobalData(String name, Object value) {
		globalData.put(name, value);
		try {
			cfg.setSharedVariable(name, value);
		} catch (TemplateModelException e) {
			e.printStackTrace();
		}
	}
	@Override
	public Object getGlobalData(String name) {
		return globalData;
	}
	@Override
	public void removeGlobalData(String name) {
		globalData.remove(name);
		try {
			cfg.clearSharedVariables();
			cfg.setSharedVaribles(globalData);
		} catch (TemplateModelException e) {
			e.printStackTrace();
		}
	}
	@Override
	public Map<String, Object> getGlobalDatas() {
		return globalData;
	}

	@Override
	public void loadConfig(Map<String,String> datas) {
		Properties prop = new Properties();
		try {
			prop.load(this.getClass().getClassLoader().getResourceAsStream(CONFIG_FILE));
		} catch (IOException e) {
			e.printStackTrace();
			return;
		}
		Set<String> keys = prop.stringPropertyNames();
		for(String key:keys) {
			if(key.startsWith(CONFIG_VARS_PREFIX)) {
				String k = key.substring(CONFIG_VARS_PREFIX.length());
				String v = prop.getProperty(key,"");
				if(datas != null) {
					Set<String> dataKeys = datas.keySet();
					for(String dk:dataKeys) {
						if(v.contains(dk)) {
							String dv = datas.get(dk);
							v = v.replace("${"+dk+"}", dv);
						}
					}
				}
				logger.debug("view put a var name={},value={}",k,v);
				this.addGlobalData(k, v);
			}
		}
	}
}
